﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Blog.TemplateEngine.Helpers;

namespace Blog.TemplateEngine.Functions
{
    class ForEachFunction : IFunction
    {
        protected INode Compile(Parser parser, Token token)
        {
            string[] source = token.Content.SplitAndTrim(' ');
            if (source.Length != 4)
            {
                throw new TemplateException("'foreach' statements should have 4 parameters: foreach 'variable' in 'collection'");
            }

            NodeList body = parser.Parse(new string[] { "end" });
            parser.DeleteNextToken();

            return new ForEachNode(body, source[1], source[3]);
        }

        INode IFunction.Compile(Parser parser, Token token)
        {
            return Compile(parser, token);
        }
    }

    class ForEachData
    {
        public ForEachData Parent { get; set; }
        public int Index { get; set; }
        public bool IsEven { get { return (Index % 2) == 0; } }
        public bool IsOdd { get { return (Index % 2) == 1; } }
        public bool IsFirst { get; set; }
        public bool IsLast { get; set; }
    }

    class ForEachNode : INode
    {
        NodeList mBody;
        string mCollection;
        string mVariable;

        public ForEachNode(NodeList body, string variable, string collection)
        {
            mBody = body;
            mVariable = variable;
            mCollection = collection;
        }

        protected string Render(Context context)
        {
            var result = new StringBuilder();
            object collection = VariableResolver.Resolve(context, mCollection);
            if (typeof(IEnumerable).IsAssignableFrom(collection.GetType()))
            {
                //List<object> list = new List<object>((IEnumerable<object>)collection);
                var enumerator = ((IEnumerable)collection).GetEnumerator();
                List<object> list = new List<object>();
                while (enumerator.MoveNext())
                {
                    list.Add(enumerator.Current);
                }
                
                var data = new ForEachData();

                context.Push();
                if (context.ContainsKey("foreach"))
                {
                    data.Parent = (ForEachData)context["foreach"];
                }
                context["foreach"] = data;

                for (int i = 0; i < list.Count; i++)
                {
                    context[mVariable] = list[i];
                    data.Index = i;
                    data.IsFirst = i == 0;
                    data.IsLast = i == list.Count - 1;
                    result.Append(mBody.Render(context));
                }
                context.Pop();
            }

            return result.ToString();
        }

        string INode.Render(Context context)
        {
            return Render(context);
        }
    }
}
